package com.swn.common.util;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.sql.Types;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFDataFormat;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.support.rowset.SqlRowSet;
import org.springframework.jdbc.support.rowset.SqlRowSetMetaData;
import org.springframework.stereotype.Repository;
/**
 * Excel导出类
 * @author XieJz
 *
 */

@Repository
public class ExportUtil{
		//项目路径
		private static final String proPath="D:\\apache-tomcat-7.0.47\\webapps\\commonFrame";
		//模板路径
		private static final String basePath=proPath+"\\file\\excel\\template\\";
		//导出路径
		private static final String outPath =proPath+"\\file\\excel\\download\\";
		//单元格样式(居中)
		private static final short cellAlign = XSSFCellStyle.ALIGN_CENTER;
		//单元格样式(居中)
		private static final short cellVAlign = XSSFCellStyle.VERTICAL_CENTER;
		//单元格高度
		private static final short cellHeight = 20;
		private static CellStyle style;
		@Autowired
		private JdbcTemplate jdbcTemplate;
		
		
		/**
		 * 导出Excel文件
		 * @param sql	数据库sql
		 * @param templateName	模板名称(确保模板在模板路径下)
		 * @param colNames	导出列名
		 * @param fileName	导出文件名
		 * @return	文件所在文件夹(随机生成)保存路径
		 * @throws FileNotFoundException
		 * @throws IOException
		 */
		public String outputFile(String sql ,String templateName,List<String> colNames) throws FileNotFoundException, IOException{
			List<Map<String,Object>> objList =  queryForExport(sql);
			XSSFWorkbook wb = getTemplateFile(templateName);
			insertTable(wb, objList, colNames);
			return createFile(wb);
		}
		/**
		 * 导出Excel文件
		 * @param result	检索结果(可以使用jdbcTemplate的queryForList方法)
		 * @param templateName	模板名称(确保模板在模板路径下)
		 * @param colNames	导出列名
		 * @param fileName	导出文件名
		 * @return	文件所在文件夹(随机生成)保存路径
		 * @throws FileNotFoundException
		 * @throws IOException
		 */
		public  String outputFile(List<Map<String, Object>> result,String templateName,List<String> colNames) throws FileNotFoundException, IOException{
			XSSFWorkbook wb = getTemplateFile(templateName);
			insertTable(wb, result, colNames);
			return createFile(wb);
		}
		/**
		 * 导出Excel文件
		 * @param result	检索结果(可以使用jdbcTemplate的queryForList方法)
		 * @param templateName	模板名称(确保模板在模板路径下)
		 * @param colNames	导出列名
		 * @param fileName	导出文件名
		 * @return
		 * @throws FileNotFoundException
		 * @throws IOException
		 */
		public  String outputFile(List<Map<String, Object>> result,String templateName,String colNames) throws FileNotFoundException, IOException{
			XSSFWorkbook wb=getTemplateFile(templateName);
			insertTable(wb, result, colNames);
			return createFile(wb);
		}
		/**
		 * 导出Excel文件
		 * @param sql	数据库sql
		 * @param templateName	模板名称(确保模板在模板路径下)
		 * @param colNames	导出列名
		 * @return	文件所在文件夹(随机生成)保存路径
		 * @throws FileNotFoundException
		 * @throws IOException
		 */
		public  String outputFile(String sql,String templateName,String colNames,String fileName) throws FileNotFoundException, IOException{
			List<Map<String,Object>> objList =  queryForExport(sql);
			XSSFWorkbook wb=getTemplateFile(templateName);
			insertTable(wb, objList, colNames);
			return createFile(wb);
		}
		/**
		 * 导出Excel文件
		 * @param sql	数据库sql
		 * @param templateName	模板名称(确保模板在模板路径下)
		 * @param titleParam	模板表头参数
		 * @param colNames	导出列名
		 * @return	文件所在文件夹(随机生成)保存路径
		 * @throws FileNotFoundException
		 * @throws IOException
		 */
		public String outputFile(String sql,String templateName,Map<String,String> titleParam,String colNames,String fileName) throws FileNotFoundException, IOException{
			List<Map<String,Object>> result =  queryForExport(sql);
			XSSFWorkbook wb=getDynamicTemplateFile(templateName, titleParam);
			insertTable(wb, result, colNames);
			return createFile(wb);
		}
		/**
		 * 导出Excel文件
		 * @param result	检索结果(可以使用jdbcTemplate的queryForList方法)
		 * @param templateName	模板名称(确保模板在模板路径下)
		 * @param titleParam	模板表头参数
		 * @param colNames	导出列名(用逗号隔开)
		 * @return	文件所在文件夹(随机生成)保存路径
		 * @throws FileNotFoundException
		 * @throws IOException
		 */
		public String outputFile(List<Map<String, Object>> result,String templateName,Map<String,String> titleParam
						,String colNames) throws FileNotFoundException, IOException{
			XSSFWorkbook wb=getDynamicTemplateFile(templateName, titleParam);
   			insertTable(wb, result, colNames);
			return createFile(wb);
		}
		/**
		 * 导出Excel文件
		 * @param sql	数据库sql
		 * @param templateName	模板名称(确保模板在模板路径下)
		 * @param titleParam	模板表头参数
		 * @param colNames	导出列名(用逗号隔开)
		 * @return	文件所在文件夹(随机生成)保存路径
		 * @throws FileNotFoundException
		 * @throws IOException
		 */
		public String outputFile(String sql,String templateName,Map<String,String> titleParam,
				List<String> colNames) throws FileNotFoundException, IOException{
			XSSFWorkbook wb=getDynamicTemplateFile(templateName, titleParam);
			List<Map<String,Object>> result =  queryForExport(sql);
			insertTable(wb, result, colNames);
			return createFile(wb);
		}
		/**
		 * 导出Excel文件
		 * @param result	检索结果(可以使用jdbcTemplate的queryForList方法)
		 * @param templateName	模板名称(确保模板在模板路径下)
		 * @param titleParam	模板表头参数
		 * @param colNames	导出列名
		 * @return	文件所在文件夹(随机生成)保存路径
		 * @throws FileNotFoundException
		 * @throws IOException
		 */
		public String outputFile(List<Map<String, Object>> result,String templateName,Map<String,String> titleParam
				,List<String> colNames) throws FileNotFoundException, IOException{
			XSSFWorkbook wb=getDynamicTemplateFile(templateName, titleParam);
			insertTable(wb, result, colNames);
			return createFile(wb);
		}
		//生成文件到download
		private String createFile(XSSFWorkbook wb) throws FileNotFoundException, IOException{
			String randomPath = UUIDUtil.getUUID();
			wb.write(new FileOutputStream(outPath+randomPath+".xlsx"));
			return outPath+randomPath+".xlsx";
		}
		/**
		 * 获取检索结果,适用只传sql的情况
		 * @param sql
		 * @return
		 */
		private List<Map<String,Object>> queryForExport(String sql){
			List<Map<String,Object>> result = jdbcTemplate.queryForList(sql);
			return result;
		}
		
		  
		public JdbcTemplate getJdbcTemplate() {
			return jdbcTemplate;
		}
		public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
			this.jdbcTemplate = jdbcTemplate;
		}
		/**
		 * 获取POI的Excel文件封装对象,适用于Excel2007+
		 * @param 模板名称(确保模板在模板路径下)
		 * @return	POI的Excel文件封装对象
		 */
		private  XSSFWorkbook getTemplateFile(String name){
			String finalPath = basePath+name;
			XSSFWorkbook wb;
			try{
			 wb =new XSSFWorkbook(new FileInputStream(finalPath));
			 return wb;
			}catch(FileNotFoundException e){
				e.printStackTrace();
				System.err.println("文件路径错误,请检查模板路径."+finalPath);
				return new XSSFWorkbook();
			}catch(IOException e){
				e.printStackTrace();
				System.err.println("IO异常,请检查模板文件."+finalPath);
				return new XSSFWorkbook();
			}
		}
		
		/**
		 * 动态表头赋值
		 * @param templateName
		 * @param data 动态数据
		 * @return
		 */
		private XSSFWorkbook getDynamicTemplateFile(String templateName,Map<String,String> paramMap){
			XSSFWorkbook wb = getTemplateFile(templateName);

			// 第一个不为空的行
			int firstRowNum = wb.getSheetAt(0).getFirstRowNum();
			// 最后一个不为空的行
			int lastRowNum = wb.getSheetAt(0).getLastRowNum();

			XSSFSheet sheet = wb.getSheetAt(0);
			XSSFRow hssfRow = sheet.getRow(firstRowNum);
			// 实际有效的列（不包括空列）
			int columnNum = hssfRow.getPhysicalNumberOfCells();
			// 第一个不为空的列
			int firstCellNum = hssfRow.getFirstCellNum();
			// int lastCellNum = hssfRow.getLastCellNum();有问题，自己计算
			// 最后一个不为空的列
			int lastCellNum = firstCellNum + columnNum - 1;

			Row row = null;
			Cell cell = null;
			String value = "";
			String[] splits;
			String[] splits2;
			for (int i = firstRowNum; i <= lastRowNum; i++) {
				row = sheet.getRow(i);
				// 不为空行，则下下执行。有的中间有空行，则为null
				if (row != null) {
					for (int j = firstCellNum; j <= lastCellNum; j++) {
						cell = row.getCell(j);
						if (cell != null) {
							value = cell.getStringCellValue();
							if (value.contains("{")) {
								splits = value.split("\\{");
								for (String str : splits) {
									if (str.contains("}")) {
										splits2 = str.split("\\}");
										cell.setCellValue(value.replaceAll("\\{"
												+ splits2[0] + "\\}",
												paramMap.get(splits2[0])));
									}
								}
							}
						}
					}
				}
			}
			return wb;
		}
		
		
		
		/**
		 * 向XSSFWorkbook对象插入数据
		 * @param templateName
		 * @param result
		 * @param colNames
		 * @return
		 * @throws FileNotFoundException
		 * @throws IOException
		 */
		private  XSSFWorkbook insertTable(XSSFWorkbook wb,List<Map<String, Object>> result,List<String> colNames) throws FileNotFoundException, IOException{
			//第一个不为空的行
			int firstRowNum= wb.getSheetAt(0).getFirstRowNum();
			//最后一个不为空的行
			int lastRowNum = wb.getSheetAt(0).getLastRowNum();

			XSSFSheet sheet = wb.getSheetAt(0);
			XSSFRow hssfRow=sheet.getRow(firstRowNum);
			//实际有效的列（不包括空列）
			int columnNum=hssfRow.getPhysicalNumberOfCells();
			//第一个不为空的列
			int firstCellNum =  hssfRow.getFirstCellNum();
			//int lastCellNum = hssfRow.getLastCellNum();有问题，自己计算
			//最后一个不为空的列
			int lastCellNum = firstCellNum + columnNum -1;
			
			Row row;
			Cell cell;
			Map<String,Object> record;//插入数据
			for(int i= 0 ;i<result.size();i++){
				row =sheet.createRow(i+lastRowNum+1);
				row.setHeightInPoints(cellHeight);
				record=result.get(i);    
				for(int j=firstCellNum,p=0;j<=lastCellNum;j++,p++){
					cell = row.createCell(j);
					style = wb.createCellStyle();//实例化cellstyle
					 style.setAlignment(cellAlign);
					 style.setVerticalAlignment(cellVAlign);
					 setBorder(style);
					try{
						try{
							cell.setCellValue(Long.parseLong(record.get(colNames.get(j)).toString()));
							}catch(NumberFormatException e){
								cell.setCellValue(record.get(colNames.get(j)).toString());
							}
						cell.setCellStyle(style);
					
					}catch(Exception e){
						cell.setCellValue(record.get(colNames.get(p)).toString());
					}
				}
			}
			return wb;
		}
		
		/**
		 * 向XSSFWorkbook对象插入数据
		 * @param templateName
		 * @param colsName
		 * @param result
		 * @return
		 * @throws IOException 
		 * @throws FileNotFoundException 
		 */
		private XSSFWorkbook insertTable(XSSFWorkbook wb,List<Map<String,Object>> result,String colsName) throws FileNotFoundException, IOException{
			List<String> colsNames = getColNames(colsName);
			return insertTable(wb,result,colsNames);
		}
		
		//根据一个逗号间隔的字符串获取列名列表
		public static List<String> getColNames(String colsName){
			String[] colNames;
			colNames = colsName.split(",");
			List<String> result = new ArrayList<String>();
			for(int i=0;i<colNames.length;i++){
				result.add(colNames[i]);
			}
			return result;
		}
		
		
		public static CellStyle setBorder(CellStyle style) {
			style.setBorderBottom(CellStyle.BORDER_THIN); // 下边框
			style.setBorderLeft(CellStyle.BORDER_THIN);// 左边框
			style.setBorderTop(CellStyle.BORDER_THIN);// 上边框
			style.setBorderRight(CellStyle.BORDER_THIN);// 右边框
			return style;
		}
}
